﻿using System;
using System.Collections;
using Unity.VisualScripting;
using UnityEngine;

namespace Gameplay.CharacterFramework
{
    public abstract class Role:MonoBehaviour,IDamageable
    {
        public CharacterData Data;
        public CharacterStatus Status;
        protected ComponentManager _componentManager;
        protected PhysicsComponent _physicsComponent;
        protected AnimationComponent _animationComponent;
        protected SkillManager _skillManager;
        protected ParticleManager _particleManager;
        protected CapsuleCollider _collider;
        public PhysicsComponent PhysicsComponent => _physicsComponent;
        public AnimationComponent AnimationComponent => _animationComponent;
        public ParticleManager ParticleManager => _particleManager;

        public SkillManager SkillManager => _skillManager;

        private InfomediaryAnimation _infomediaryAnimation;

        protected WeaponManager _weaponManager;
        public WeaponManager WeaponManager => _weaponManager;

        protected Sensor _sensor;

        protected Vector3 _direction;
        public Vector3 Direction => _direction;

       

        protected virtual void Awake() 
        {
            if(!TryGetComponent<SkillManager>(out _skillManager)) 
            {
                Debug.LogWarning("未找到技能管理器");
            }
            _infomediaryAnimation=GetComponentInChildren<InfomediaryAnimation>();

            if (!_infomediaryAnimation)
            {
                Debug.LogWarning("未找到技能转接类");
            }
            if (!TryGetComponent<WeaponManager>(out _weaponManager))
            {
                Debug.LogWarning("未找到武器管理器");
            }
            if (!TryGetComponent<CapsuleCollider>(out _collider))
            {
                Debug.LogWarning("未找到武器管理器");
            }
        }

        protected virtual void Start()
        {
            _componentManager=GetComponentInChildren<ComponentManager>();
            if (!_componentManager)
            {
                Debug.LogWarning("未找到ComonentManager");
            }
            else
            {
                _physicsComponent = _componentManager.GetCoreComponent<PhysicsComponent>();
                _animationComponent = _componentManager.GetCoreComponent<AnimationComponent>();
                _sensor = _componentManager.GetCoreComponent<Sensor>();
                _particleManager = _componentManager.GetCoreComponent<ParticleManager>();
            }

            _skillManager.Init(this);

            _infomediaryAnimation.OnSkillStartEvent += SkillStart;
            _infomediaryAnimation.OnSkillTriggerEvent += SkillTrigger;
            _infomediaryAnimation.OnSkillFinishEvent += SkillFinish;
            _infomediaryAnimation.OnSkillEndEvent += SkillEnd;

            Status.Init();
        }

        private void OnDisable()
        {
            _infomediaryAnimation.OnSkillStartEvent -= SkillStart;
            _infomediaryAnimation.OnSkillTriggerEvent -= SkillTrigger;
            _infomediaryAnimation.OnSkillFinishEvent -= SkillFinish;
            _infomediaryAnimation.OnSkillEndEvent -= SkillEnd;
        }
        private void SkillTrigger()
        {
            _skillManager.SkillTrigger();
        }

        private void SkillStart()
        {
            _skillManager.OnSkill();
        }
        private void SkillFinish()
        {
            _skillManager.SkillFinish();
        }
        private void SkillEnd()
        {
            _skillManager.SkillEnd();
        }

        protected virtual void Update() 
        {
            _componentManager.LogicUpdate();
            _skillManager.SkillUpdate();
          
            _animationComponent.SetFloat("velocity", _direction.magnitude, 0.1f, Time.deltaTime);
            _animationComponent.SetFloat("yVelocity", _physicsComponent.CurrentVelocity.y);
            _animationComponent.SetBool("isGrounded", _sensor.IsGrounded);
            _animationComponent.SetBool("isDead", Status.IsDead);
            _animationComponent.SetBool("isDamage", Status.IsDamage);
            _animationComponent.SetBool("isUsing", Status.IsUsing);
            _animationComponent.SetBool("isFalling", Status.IsFalling);

            if (CanStatic()) 
            {
                Static();

            }else if (CanFalling()) 
            {
                Falling();
            }
        }

        protected virtual void FixedUpdate() 
        {
            _componentManager.PhysicsUpdate();
        }

        public virtual void Static()
        {
           
            _direction = Vector3.zero;
            _physicsComponent.SetVelocity(0, 0, 0);
            
            
        }

        protected virtual bool CanStatic()
        {
            if (_direction.magnitude<=0&&_sensor.IsGrounded && !Status.IsDead && !Status.IsDamage&&!Status.IsUsing) 
            {
                return true;
            }
            else 
            {
                return false;
            }
        }

        private bool CanFalling()
        {
            if(_physicsComponent.CurrentVelocity.y < -2f && !_sensor.IsGrounded&&!Status.IsDead&&!Status.IsDamage) 
            {
                return true;
            }
            else 
            {
                Status.IsFalling = false;
                return false;
            }
        }

        private void Falling()
        {
            Status.IsFalling = true;
            _physicsComponent.SetVelocity(0, _physicsComponent.CurrentVelocity.y, 0);
        }


        public virtual void Move(Vector3 direction, float speed)
        { 
            _direction = direction;
            Rigidbody rb = _physicsComponent.RB;
            Vector3 targetPosition = rb.position + speed * direction.normalized * Time.deltaTime;
            Vector3 targetVelocity = (targetPosition - transform.position) / Time.deltaTime;
            
            _physicsComponent.SetVelocity(targetVelocity.x,rb.velocity.y,targetVelocity.z);
        }
        public virtual bool MoveToTarget(Vector3 targetPos)
        {
            Vector3 direction;
            targetPos.y = 0;
            Vector3 currentPos = new Vector3(transform.position.x, 0, transform.position.z);
            if ((targetPos - currentPos).magnitude <= 0.3f)
            {
                direction = Vector3.zero;
                _physicsComponent.SetVelocity(0, _physicsComponent.CurrentVelocity.y, 0);
                return true;
            }
            else
            {
                direction = targetPos - currentPos;
                direction.Normalize();
                Move(direction);

                return false;
            }
        }
        protected virtual void Rotate(Vector3 direction)
        {
            direction.y = 0;
            Vector3 targetForward = Vector3.RotateTowards(transform.forward, direction.normalized, Data.Config.InitialRotateSpeed * Time.deltaTime, .01f);
            Quaternion rotate = Quaternion.LookRotation(targetForward);
            transform.rotation = rotate;
        }
        public virtual void Move(Vector3 direction)
        {
            if (CanMove())
            {
                Status.MoveSpeed = Data.Config.InitialMoveSpeed;
                Move(direction, Status.MoveSpeed);
                Rotate(direction);
            }
        }

        public virtual bool CanMove()
        {
            if (!Status.IsDead && !Status.IsDamage && !Status.IsUsing) 
            {
                return true;
            }
            else 
            {
                return false;
            }
        }
 
        public void TakeDamage(Role target, float damageValue, Vector3 closesPoint)
        {

            if (!Status.IsDamage)   
            {
                _physicsComponent.SetVelocity(0, _physicsComponent.CurrentVelocity.y, 0);
                Status.IsDamage = true;
                _animationComponent.SetBool("isDamage",true);
                _animationComponent.SetInteger("damageNum",1);
                transform.LookAt(target.transform.position);
                if (target.SkillManager.CurrentUseSkill.Config.HitSound != null)
                {
                    AudioManager.Instance.PlaySound(target.SkillManager.CurrentUseSkill.Config.HitSound);
                }
                if (target.SkillManager.CurrentUseSkill.Config.HitVFX != null)
                {
                    _particleManager.PlayEffect(target.SkillManager.CurrentUseSkill.Config.HitVFX, closesPoint);
                }
                Status.HP -= damageValue;
                StartCoroutine(WaitForReset(1));
            }
        }

        private IEnumerator WaitForReset(float waitTime)
        {
            yield return new WaitForSeconds(waitTime);
            _animationComponent.SetBool("isDamage", false);
            Status.IsDamage = false;
        }

        public virtual void Die() 
        {
            Debug.Log("人物死亡");
            if (!Status.IsDead) 
            {
                Status.IsDead = true;
                _physicsComponent.SetVelocity(0, _physicsComponent.CurrentVelocity.y, 0);
                _physicsComponent.RB.isKinematic = true;
                _collider.enabled = false;

            }
            
        }

        public virtual void UseSkill(int weaponId, int skillId)
        {
            if (CanOnSkill()) 
            {
                _weaponManager.SelectWeapon(weaponId);
                
                _skillManager.RegisterSkill(_weaponManager.CurrentWeapon);
                _skillManager.UseSkill(skillId);
            }
        }
        public virtual void UseSkill(int skillId) 
        {
            if (CanOnSkill()) 
            {
                if (_weaponManager.CurrentWeapon != null) 
                {
                    _skillManager.RegisterSkill(_weaponManager.CurrentWeapon);
                    _skillManager.UseSkill(skillId);
                }
            }
        }

        public virtual void UseSkill(int weaponId, int skillId,Role target)
        {
            if (CanOnSkill())
            {
                _weaponManager.SelectWeapon(weaponId);

                _skillManager.RegisterSkill(_weaponManager.CurrentWeapon);
                _skillManager.UseSkill(skillId,target);
            }
        }

        public virtual bool CanOnSkill()
        {
            if (!Status.IsDead&&!Status.IsDamage&&!Status.IsUsing) 
            {
                return true;
            }
            else 
            {
                return false;
            }
        }

        public void TakeDamage(Vector3 pos, AttackDetails details)
        {
            if (!Status.IsDamage)
            {
                Role target = details.Target;
                _physicsComponent.SetVelocity(0, _physicsComponent.CurrentVelocity.y, 0);
                Status.IsDamage = true;
                _animationComponent.SetBool("isDamage", true);
                _animationComponent.SetInteger("damageNum", 1);
                transform.LookAt(target.transform.position);
                if (target.SkillManager.CurrentUseSkill.Config.HitSound != null)
                {
                    AudioManager.Instance.PlaySound(target.SkillManager.CurrentUseSkill.Config.HitSound);
                }
                if (target.SkillManager.CurrentUseSkill.Config.HitVFX != null)
                {
                    _particleManager.PlayEffect(target.SkillManager.CurrentUseSkill.Config.HitVFX, pos);
                }
                Status.HP -= details.Damage;
                StartCoroutine(WaitForReset(1));
            }
        }
    }
}
